<script setup>
import {
  ImageLayer,
  Marker,
  MarkerLayer,
  PolygonLayer,
  Popup,
  Scene,
} from '@antv/l7'
import { GaodeMap, Map } from '@antv/l7-maps'
import { featureCollection, point } from '@turf/helpers'
import center from '@turf/center'

import imgMapMarker from '@/assets/image/index/map-marker.png'
import imgMapMarkerActive from '@/assets/image/index/map-marker--active.png'
import imgMap from '@/assets/image/index/map.png'
import { geoJsonData } from '@/pages/__view-constant/index'
import { clusterThreshold } from '@/config'

const props = defineProps({
  data: {
    type: Object,
    required: true,
  },
  ready: {
    type: Boolean,
    default: false,
  },
})

let scene = null
const activeMarker = shallowRef(null)
const markerLayer = ref(null)
const popupRef = ref(null)

const state = reactive({
  mounted: false,
  mountCheckCount: 0,
  sceneLoaded: false,
  sceneLoadCheckCount: 0,
  markerInited: false,
  currentDeptIndex: -1,
  currentDept: {},
})

const destructionList = computed(() => props.data?.destructionList || [
  {
    deptId: 1,
    deptName: '济南本部公司',
    coordinate: '117.136133, 36.679511',
    totalNum: 100,
    monthNum: 20,
    yearNum: 200,
    paperNum: 30,
    multiNum: 70,
  },
  {
    deptId: 2,
    deptName: '1号分公司',
    coordinate: '117.136133, 36.629511',
    totalNum: 200,
    monthNum: 40,
    yearNum: 400,
    paperNum: 120,
    multiNum: 100,
  },
  {
    deptId: 3,
    deptName: '2号分公司',
    coordinate: '117.146133, 36.659511',
    totalNum: 200,
    monthNum: 40,
    yearNum: 400,
    paperNum: 120,
    multiNum: 100,
  },
])

function groupCoordinates(list, threshold) {
  // 将坐标转换为对象，以便于比较和分组
  const groupIndexArray = []
  list.forEach((item, index) => {
    if(item.coordinate && item.coordinate.includes(',')) {
      groupIndexArray.push({ ...item, group: index, originIndex: index })
    }
  })

  // 比较并分组
  groupIndexArray.sort((a, b) => a.group - b.group) // 确保按初始分组排序
  for (let i = 0; i < groupIndexArray.length; i++) {
    for (let j = i + 1; j < groupIndexArray.length; j++) {
      const [lng1, lat1] = groupIndexArray[i].coordinate.split(',')
      const [lng2, lat2] = groupIndexArray[j].coordinate.split(',')
      // 计算两个坐标之间的差值
      const diff = Math.abs(parseFloat(lng1) - parseFloat(lng2))
        + Math.abs(parseFloat(lat1) - parseFloat(lat2))
      // 如果差值小于阈值，则将它们分到同一组
      if(diff < threshold) {
        const maxGroup = Math.max(groupIndexArray[i].group, groupIndexArray[j].group)
        groupIndexArray[i].group = maxGroup
        groupIndexArray[j].group = maxGroup
      }
    }
  }

  // 根据组号对坐标进行分组
  const groups = {}
  groupIndexArray.forEach((item) => {
    const { group, coordinate } = item
    const [lng, lat] = coordinate.split(',')
    item.coordNums = [parseFloat(lng), parseFloat(lat)]
    if(!groups[group]) {
      groups[group] = []
    }
    groups[group].push(item)
  })

  // 返回分组结果
  return Object.values(groups)
}

const updateMarkers = () => {
  if(markerLayer.value) {
    markerLayer.value.clear()
    setMarkers()
  }
}

const createSceneView = () => {
  const sceneInstance = new Scene({
    id: 'l7map',
    map: new Map({
    // map: new BaiduMap({
    // map: new GaodeMap({
      // center: [117.120171, 36.652223],
      center: [116.520171, 33.652223],
      zoom: 8,
      pitch: 0,
      rotation: 0,
      minZoom: 2,
      maxZoom: 12,
      // style: 'blank',
      // token: 'ce89d6a6ba0901aade5dd6fafd194a73',
    }),
    logoVisible: false,
  })
  sceneInstance.on('loaded', () => {
    const mapUILayer = new ImageLayer({
      // autoFit: true,
    })
    mapUILayer.source(
      imgMap,
      {
        parser: {
          type: 'image',
          // extent: [116.226064, 35.990622, 117.975331, 37.532886],
          extent: [116.236064, 35.896622, 117.975331, 37.532886],
        },
      },
    )
    sceneInstance.addLayer(mapUILayer)

    const mapDataLayer = new PolygonLayer({
      // autoFit: true,
    })

    mapDataLayer.source(geoJsonData)
      .shape('fill')
      .color('rgba(0, 0, 0, 1)')
      .active({
        color: '#0EF',
        mix: 0.0125,
      })
      .style({
        opacity: 0.1,
      })

    sceneInstance.addLayer(mapDataLayer)
    sceneInstance.fitBounds([[116.336064, 35.896622], [117.975331, 37.532886]], { animate: false }) // 最小精度加了0.1以使地图视觉居中
    sceneInstance.startAnimate()
    state.sceneLoaded = true
  })
  return sceneInstance
}

const setMarkers = () => {
  try {
    const mapMarkerLayer = new MarkerLayer({
      // name: 'deptMarkerLayer',
      autoFit: true,
      // cluster: true,
    })

    const clusteredDepts = groupCoordinates(destructionList.value, clusterThreshold)
    clusteredDepts.forEach((clusterItems, index) => {
      if(!clusterItems?.length || !clusterItems[0]?.coordNums) {
        return
      }
      let centerCoordinate = clusterItems[0].coordNums

      try {
        if(clusterItems.length > 1) {
          const pointCoords = clusterItems.map((item) => {
            return point(item.coordNums)
          })
          const features = featureCollection(pointCoords)
          const centerPoint = center(features)
          centerCoordinate = centerPoint.geometry.coordinates
        }
      }
      catch (error) {
        console.log('%c%s', 'font-size:2em;background: #DD5644;color: #FFF', 'error', error)
      }

      const [lng, lat] = centerCoordinate
      const el = document.createElement('label')
      el.className = 'dept-marker'
      el.id = `dept-marker__${index}`
      el.innerHTML = `
          <div class="dept-marker__wrap data-item="${JSON.stringify(clusterItems)}" style='width:40px;height:68px;'">
            <img src="${imgMapMarker}" />
          </div>
        `
      const elActive = document.createElement('label')
      elActive.classList.add('dept-marker')
      elActive.classList.add('active')
      elActive.style.zIndex = '8'
      elActive.style.userSelect = 'none'
      elActive.style.pointerEvents = 'none'
      elActive.innerHTML = `
          <div class="dept-marker__wrap" style='width:40px;height:68px;'>
            <img src="${imgMapMarkerActive}" />
          </div>
        `

      const marker = new Marker({
        element: el,
        draggable: false,
        extData: { targetDepts: clusterItems },
        offsets: [0, 0],
        anchor: 'center',
      })
      marker.setLnglat({ lng, lat })
      marker.on('click', (e) => {
        const elem = marker.getElement()
        const newElActive = document.createElement('label')
        newElActive.classList.add('dept-marker')
        newElActive.classList.add('active')
        newElActive.id = `dept-marker__${index}`
        newElActive.style.zIndex = '8'
        newElActive.style.userSelect = 'none'
        newElActive.style.pointerEvents = 'none'
        newElActive.innerHTML = `
            <div class="dept-marker__wrap" style='width:40px;height:68px;'>
              <img src="${imgMapMarkerActive}" />
            </div>
          `
        marker.setElement(newElActive)
        state.currentDept = e.data.targetDepts[0]
        state.currentDeptIndex = e.data.targetDepts[0].originIndex
        if(activeMarker.value && !elem.classList.contains('active')) {
          const newElInactive = document.createElement('label')
          newElInactive.className = 'dept-marker'
          newElInactive.id = `dept-marker__${index}`
          newElInactive.innerHTML = `
              <div class="dept-marker__wrap data-item="${JSON.stringify(clusterItems)}" style='width:40px;height:68px;'">
                <img src="${imgMapMarker}" />
              </div>
            `
          activeMarker.value.setElement(newElInactive)
        }
        activeMarker.value = marker

        const popupElem = document.createElement('div')
        popupElem.classList.add('map-popup')
        e.data.targetDepts.forEach((item, index) => {
          const popupItemElem = document.createElement('div')
          popupItemElem.style.background = 'linear-gradient(249deg,#021235 0%, #009de3 100%)'
          popupItemElem.style.border = '2px solid #009de3'
          if(index !== 0) {
            popupItemElem.style.marginTop = '6px'
          }
          popupItemElem.innerHTML = `
            <div style="padding:16px;">
              <div style="min-width:180px; height:28px;line-height:28px;font-size:20px;font-weight:600;overflow:hidden;">${item.deptName}</div>
              <div style="height:1px;margin: 3px 0;background:linear-gradient(90deg, #009de3, #009de31A 100%)"></div>
              <div style="height:28px;line-height:28px;font-size:14px;font-weight:400;">累计总量 :<span style="margin-left:5px">${item.totalNum}</span></div>
            </div>
          `
          popupItemElem.addEventListener('click', (ep) => {
            console.log('%c%s', 'font-size:2em;background: #00965E;color: #FFF', 'PopupItem click', ep, this)
            state.currentDept = item
            state.currentDeptIndex = item.originIndex
          }, { capture: true })
          popupElem.appendChild(popupItemElem)
        })
        popupRef.value = new Popup({
          offsets: [20, 36],
          closeButton: false,
          closeOnClick: true,
          autoClose: true,
        })
          .setLngLat(e.lngLat)
          .setHTML(popupElem)
          .on('hide', () => {
            state.currentDeptIndex = -1
            state.currentDept = {}
            if(activeMarker.value && !elem.classList.contains('active')) {
              const newElInactive = document.createElement('label')
              newElInactive.className = 'dept-marker'
              newElInactive.id = `dept-marker__${index}`
              newElInactive.innerHTML = `
                  <div class="dept-marker__wrap data-item="${JSON.stringify(clusterItems)}" style='width:40px;height:68px;'">
                    <img src="${imgMapMarker}" />
                  </div>
                `
              activeMarker.value.setElement(newElInactive)
              activeMarker.value = null
            }
          })

        scene.addPopup(popupRef.value)
      })
      mapMarkerLayer.addMarker(marker)
    })
    scene.addMarkerLayer(mapMarkerLayer)
    markerLayer.value = mapMarkerLayer
    state.markerInited = false
  }
  catch (error) {
    console.log('%c%s', 'font-size:2em;background: #DD5644;color: #FFF', 'error', error)
  }
}
// const setMarkers = () => {
//   try {
//     const mapMarkerLayer = new MarkerLayer({
//       // name: 'deptMarkerLayer',
//       autoFit: true,
//       // cluster: true,
//     })

//     destructionList.value.forEach((item, index) => {
//       if(!item.coordinate) {
//         return
//       }
//       const [lng, lat] = item.coordinate.split(',').map(Number)
//       const el = document.createElement('label')
//       el.className = 'dept-marker'
//       el.innerHTML = `
//           <div class="dept-marker__wrap style='width:40px;height:68px;'">
//             <img src="${imgMapMarker}" />
//           </div>
//         `
//       const elActive = document.createElement('label')
//       elActive.className = 'dept-marker'
//       elActive.style.zIndex = '8'
//       elActive.innerHTML = `
//           <div class="dept-marker__wrap" style='width:40px;height:68px;'>
//             <img src="${imgMapMarkerActive}" />
//           </div>
//         `
//       const marker = new Marker({
//         element: el,
//         draggable: false,
//         extData: item,
//         offsets: [0, 0],
//         anchor: 'center',
//       })
//       marker.setLnglat({ lng, lat })
//       marker.on('click', (e) => {
//         if(state.currentDept?.deptId === e.data?.deptId) {
//           return
//         }
//         marker.setElement(elActive)
//         state.currentDept = e.data
//         state.currentDeptIndex = index
//         if(activeMarker.value) {
//           activeMarker.value.setElement(el)
//         }
//         activeMarker.value = marker
//       })
//       marker.on('mouseover', (e) => {
//         const popupElem = document.createElement('div')
//         popupElem.classList.add('map-popup')
//         popupElem.innerHTML = `
//         <div style="background: linear-gradient(249deg,#021235 0%, #009de3 100%); border: 2px solid #009de3;">
//           <div style="padding:16px;">
//             <div style="min-width:180px; height:28px;line-height:28px;font-size:20px;font-weight:600;overflow:hidden;">${e.data.deptName}</div>
//             <div style="height:1px;margin: 3px 0;background:linear-gradient(90deg, #009de3, #009de31A 100%)"></div>
//             <div style="height:28px;line-height:28px;font-size:14px;font-weight:400;">累计总量 :<span style="margin-left:5px">${e.data.totalNum}</span></div>
//           </div>
//         </div>
//         `
//         popupRef.value = new Popup({
//           offsets: [0, 36],
//           closeButton: false,
//         })
//           .setLngLat(e.lngLat)
//           .setHTML(popupElem)

//         scene.addPopup(popupRef.value)
//       })
//       marker.on('mouseout', () => {
//         popupRef.value && popupRef.value.hide()
//       })
//       mapMarkerLayer.addMarker(marker)
//     })
//     scene.addMarkerLayer(mapMarkerLayer)
//     markerLayer.value = mapMarkerLayer
//     state.markerInited = false
//   }
//   catch (error) {
//     // console.log('%c%s', 'font-size:2em;background: #DD5644;color: #FFF', 'error', error)
//   }
// }

watch(() => destructionList.value, (newList) => {
  if(newList.length && state.sceneLoaded && state.markerInited) {
    updateMarkers()
  }
}, { immediate: false })

watch([() => props.ready, () => state.mountCheckCount], ([val]) => {
  if(val) {
    if(!state.sceneLoaded || !state.mounted) {
      setTimeout(() => {
        state.mountCheckCount++
      }, 50)
      return
    }
    destructionList.value?.length && setMarkers()
  }
}, { immediate: true })
onMounted(() => {
  state.mounted = true
  scene = createSceneView()
})

onBeforeUnmount(() => {
  scene.destroy()
})

const viewPaperNum = computed(() => {
  return state.currentDeptIndex !== -1 ? state.currentDept.paperNum || 0 : props.data.allPaperNum || 0
})

const viewMediaNum = computed(() => {
  return state.currentDeptIndex !== -1 ? state.currentDept.multiNum || 0 : props.data.allMultiNum || 0
})

const { currentDeptIndex, currentDept } = toRefs(state)
</script>

<template>
  <section class="dispatch-stats dispatch-stats-map">
    <div style="width: 92%;height: 75.9912%;">
      <div class="map-container">
        <div class="animate-bg" />
        <div id="l7map" style="width: 100%;height: 100%;" />
      </div>
    </div>
    <div class="bottom">
      <div class="dispatch-stats__info">
        <div class="dispatch-stats__info-wrap">
          <div class="info-title">
            {{ currentDeptIndex !== -1 ? currentDept.deptName : data.deptName || '--' }}
            <!-- {{ currentDeptIndex !== -1 ? currentDept.deptName : data.destructionList[0].deptName || '--' }} -->
          </div>
          <div class="info-content">
            <div class="info-items">
              <div class="item">
                <span class="label">送销累计总量 :</span>
                <span class="value">{{ currentDeptIndex !== -1 ? currentDept.totalNum : data.allTotalNum || 0 }}</span>
              </div>
              <div class="item">
                <span class="label">本月送达量 :</span>
                <span class="value">{{ currentDeptIndex !== -1 ? currentDept.monthNum : data.allMonthNum || 0 }}</span>
              </div>
              <div class="item">
                <span class="label">本年送达量 :</span>
                <span class="value">{{ currentDeptIndex !== -1 ? currentDept.yearNum : data.allYearNum || 0 }}</span>
              </div>
            </div>
            <div class="info-separator">
              <div class="separator" />
            </div>
            <div class="fake-chart">
              <div class="fake-chart__legend-wrap">
                <div class="legend-item paper">
                  纸质文件
                </div>
                <div class="legend-item media">
                  多媒体介质
                </div>
              </div>
              <div class="fake-chart__bar-wrap">
                <div class="paper bar-item" :style="`width: ${(viewPaperNum === 0 && viewMediaNum === 0) ? 50 : viewPaperNum / (viewPaperNum + viewMediaNum) * 100}%;`">
                  <span :class="viewMediaNum && !viewPaperNum && 'isZero'">{{ viewPaperNum }}</span>
                </div>
                <div class="bar-item media">
                  <span :class="viewPaperNum && !viewMediaNum && 'isZero'">{{ viewMediaNum }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<style lang='scss' scoped>
.dispatch-stats {
  &-map {
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
    padding: 0 0 10px;
    overflow: hidden;

    &>div {
      width: 100%;
    }

    .map-container {
      position: relative;
      width: 100%;
      height: 100%;
      padding: 12px 0;
      overflow: hidden;
      border-radius: 64px;

      @keyframes spin {
        0% {
          transform: rotate(0);
        }

        20% {
          transform: rotate(72deg);
        }

        25% {
          transform: rotate(90deg) scale(1.45);
        }

        39% {
          transform: rotate(116.2deg) scale(1.45);
        }

        40% {
          transform: rotate(117deg) scale(1.6);
        }

        41% {
          transform: rotate(118.8deg) scale(1.45);
        }

        55% {
          transform: rotate(144deg) scale(1.45);
        }

        60% {
          transform: rotate(162deg);
        }

        80% {
          transform: rotate(234deg);
        }

        85% {
          transform: rotate(360deg);
        }

        100% {
          transform: rotate(1080deg);
        }
      }

      .animate-bg {
        position: absolute;
        top: 0;
        left: 0;
        z-index: -1;
        width: 100%;
        height: 100%;
        background-image: url("/src/assets/image/index/pattern-map-1.png");
        background-repeat: no-repeat;
        background-position: center;
        background-size: 100% 100%;
        animation: spin 25s cubic-bezier(0.5, 1.85, 0.5, 1.25) 0s infinite;
      }

      #l7map {
        border-radius: 64px;
        // transform: scale(var(--reverse-scale-ratio));
        :deep(.amap-container) {
          background-color: transparent !important;
          background-image: none !important;

          .amap-layers {
            display: none !important;
          }
        }

        :deep(.l7-marker-container) {
          .l7-popup {
            .l7-popup-content {
              padding: 0;
              color: #FFF;
              background-color: transparent;
            }
          }
        }
      }
    }

    .bottom {
      display: flex;
      flex: 1;
      min-height: 0;
      padding: 0 64px;
    }

    .dispatch-stats {
      &__info {
        width: 100%;

        &-wrap {
          position: relative;
          height: 100%;
          background-image: url("/src/assets/image/index/bg-main-info.png");
          background-repeat: no-repeat;
          background-position: center;
          background-size: 100% 100%;

          .info-title {
            position: absolute;
            top: 6.1728%;
            left: 15px;
            font-size: 20px;
            font-weight: 700;
            line-height: 1;
            color: transparent;
            background: linear-gradient(180deg,#fff, #a8f9ff 100%);
            background-clip: text;
          }

          .info-content {
            position: absolute;
            top: 24.6914%;
            bottom: 0;
            display: flex;
            width: 100%;
            padding: 20px 15px;
            color: #FFF;

            .info-items {
              display: flex;
              flex-direction: column;
              justify-content: space-between;
              width: max-content;

              .value {
                margin-left: 5px;
              }
            }

            .fake-chart {
              position: relative;
              flex: 1;
              min-width: 0;

              &__legend-wrap {
                text-align: right;

                .legend-item {
                  display: inline-flex;
                  align-items: center;

                  &::before {
                    display: inline-block;
                    width: 12px;
                    height: 6px;
                    margin-right: 6px;
                    content: '';
                    border-radius: 2px;
                  }

                  &.paper::before {
                    background: $chart-cyan;
                  }

                  &.media::before {
                    background: $chart-blue;
                  }

                  &+.legend-item {
                    margin-left: 20px;
                  }
                }
              }

              &__bar-wrap {
                position: absolute;
                bottom: 0;
                display: flex;
                justify-content: space-between;
                width: 100%;
                height: calc(100% - 53px);

                .bar-item {
                  position: relative;
                  display: flex;
                  align-items: flex-end;
                  justify-content: center;
                  min-width: 15px;
                  height: 100%;
                  background-color: rgb(255 255 255 / 10%);

                  span {
                    position: absolute;
                    bottom: 7px;
                    left: 10px;
                    font-size: 14px;
                    font-weight: 400;
                    line-height: 1;

                    &.isZero {
                      left: 3px;
                    }
                  }

                  &.paper {
                    /* stylelint-disable-next-line declaration-property-value-no-unknown */
                    background: rgba($chart-cyan-pure, 0.2);
                    /* stylelint-disable-next-line declaration-property-value-no-unknown */
                    border-bottom: 8px solid $chart-cyan-pure;

                    span {
                      color: $chart-cyan-pure;
                    }
                  }

                  &.media {
                    flex: 1;
                    /* stylelint-disable-next-line declaration-property-value-no-unknown */
                    background: rgba($chart-blue-dark, 0.2);
                    /* stylelint-disable-next-line declaration-property-value-no-unknown */
                    border-bottom: 8px solid $chart-blue-dark;

                    span {
                      color: $chart-blue-dark;
                    }
                  }
                }
              }
            }

            .info-separator {
              height: 100%;
              padding: 25px 30px;

              .separator {
                width: 2px;
                height: 100%;
                overflow: hidden;
                background-image: linear-gradient(180deg, #65C3FF1A 0%, #65C3FFEE 50%, #65C3FF1A 100%);
                background-size: 100% 100%;
              }
            }
          }
        }
      }
    }
  }
}
</style>
